home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 19
/
CD_ASCQ_19_010295.iso
/
dos
/
prg
/
pas
/
swag
/
egavga.swg
/
0127_Palette Fades-Transparent.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-08-24
|
15KB
|
454 lines
Program Transparent;
{ }
{ Example of How Transparency Works }
{ }
{ Programmed by David Dahl @ 1:272/38 }
{ }
{ This program is PUBLIC DOMAIN }
{ }
Uses CRT, Palette;
Type ImageArray = Array [0..15, 0..15] of Byte;
LocationRec = Record
X : Integer;
Y : Integer;
End;
VGABufferArray = Array[0..199, 0..319] of Byte;
VGABufferPtr = ^VGABufferArray;
Const BobTemplate : ImageArray =
((00,00,00,00,00,00,07,07,07,07,00,00,00,00,00,00),
(00,00,00,00,07,07,04,04,04,04,06,05,00,00,00,00),
(00,00,00,07,04,04,04,04,04,04,04,04,04,00,00,00),
(00,00,07,04,04,04,04,04,04,04,04,04,04,03,00,00),
(00,07,04,04,04,04,04,04,04,04,04,04,04,04,02,00),
(00,07,04,04,04,04,04,04,04,04,04,04,04,04,01,00),
(07,04,04,04,04,04,04,04,04,04,04,04,04,04,04,01),
(07,04,04,04,04,04,04,04,04,04,04,04,04,04,04,01),
(07,04,04,04,04,04,04,04,04,04,04,04,04,04,04,01),
(07,04,04,04,04,04,04,04,04,04,04,04,04,04,04,01),
(00,06,04,04,04,04,04,04,04,04,04,04,04,04,01,00),
(00,06,04,04,04,04,04,04,04,04,04,04,04,04,01,00),
(00,00,05,04,04,04,04,04,04,04,04,04,04,01,00,00),
(00,00,00,04,04,04,04,04,04,04,04,04,01,00,00,00),
(00,00,00,00,03,02,04,04,04,04,01,01,00,00,00,00),
(00,00,00,00,00,00,01,01,01,01,00,00,00,00,00,00));
MaxBob = 2; { 3 Bobs (0 .. 2) }
Var VGA : VGABufferPtr;
BackGround : VGABufferPtr;
WorkPage : VGABufferPtr;
Pal : PaletteArray;
BobImage : Array[0..MaxBob] of ImageArray;
BobLocation : Array[0..MaxBob] of LocationRec;
Counter1 : Integer;
Counter2 : Integer;
{-[ Set VGA Mode 13h (320 X 200 X 256 Chain 4) ]------------------------}
Procedure SetMode13h; Assembler;
ASM
MOV AX, $13
INT $10
End;
{-[ Put A 16 X 16 Image by ORing it With Background ]-------------------}
Procedure Put16X16ImageOR (Var Bob : ImageArray;
X, Y : Integer);
Var CounterX,
CounterY : Integer;
Begin
For CounterY := 0 to 15 do
For CounterX := 0 to 15 do
WorkPage^[CounterY + Y, CounterX + X] :=
WorkPage^[CounterY + Y, CounterX + X] OR Bob[CounterX, CounterY];
End;
{-[ Update Bob Positions ]----------------------------------------------}
Procedure UpdateBobs;
Var BobCounter : Integer;
Begin
For BobCounter := 0 to MaxBob do
Begin
Inc (Counter1, 1);
While (Counter1 >= 360) do
Dec(Counter1, 360);
If (Counter1 MOD 2) = 0
Then
Begin
Inc(Counter2,1);
While (Counter2 >= 360) do
Dec(Counter2, 360);
End;
BobLocation[BobCounter].X := 160 +
Round(90 * -Sin((Counter1 + (BobCounter*Counter2))*PI/180));
BobLocation[BobCounter].Y := 95 +
Round(60 * Cos((Counter2 + (BobCounter*Counter1))*PI/180));
End;
End;
{-[ Draw All Bobs To Work Buffer ]--------------------------------------}
Procedure DrawBobs;
Var BobCounter : Integer;
Begin
For BobCounter := 0 to MaxBob do
Put16X16ImageOR (BobImage[BobCounter],
BobLocation[BobCounter].X, BobLocation[BobCounter].Y);
End;
{-[ Initialize Variables ]----------------------------------------------}
Procedure InitializeVariables;
Const Tbl : Array [0..MaxBob] of Byte = (8, 16, 32);
Var BobCounter : Integer;
CX, CY : Integer;
Begin
{ Make Individual Bobs From Template }
For BobCounter := 0 to MaxBob do
Begin
BobImage[BobCounter] := BobTemplate;
For CY := 0 to 15 do
For CX := 0 to 15 do
If BobImage[BobCounter][CX,CY] <> 0
Then
BobImage[BobCounter][CX,CY] :=
BobImage[BobCounter][CX,CY] OR Tbl[BobCounter];
End;
Counter1 := 0;
Counter2 := 0;
End;
{-[ Build Palette ]-----------------------------------------------------}
Procedure BuildPalette;
Var ColorCounter : Integer;
Begin
{ Initialize Palette Buffer To All Black }
FillChar (Pal, SizeOf(Pal), 0);
For ColorCounter := 0 to 7 do
Begin
{ Make Red, Green, and Blue Bobs }
Pal[ColorCounter OR 08].Red := 21 + (ColorCounter * 6);
Pal[ColorCounter OR 16].Green := 21 + (ColorCounter * 6);
Pal[ColorCounter OR 32].Blue := 21 + (ColorCounter * 6);
{ Make Colors Where Red and Green Bobs Overlap }
Pal[ColorCounter OR 08 OR 16].Red := 21 + (ColorCounter * 6);
Pal[ColorCounter OR 08 OR 16].Green := 21 + (ColorCounter * 6);
{ Make Colors Where Red and Blue Bobs Overlap }
Pal[ColorCounter OR 08 OR 32].Red := 21 + (ColorCounter * 6);
Pal[ColorCounter OR 08 OR 32].Blue := 21 + (ColorCounter * 6);
{ Make Colors Where Green and Blue Bobs Overlap }
Pal[ColorCounter OR 16 OR 32].Green := 21 + (ColorCounter * 6);
Pal[ColorCounter OR 16 OR 32].Blue := 21 + (ColorCounter * 6);
{ Make Colors Where Red, Green and Blue Bobs Overlap }
Pal[ColorCounter OR 08 OR 16 OR 32].Red := 21+(ColorCounter * 6);
Pal[ColorCounter OR 08 OR 16 OR 32].Green := 21+(ColorCounter * 6);
Pal[ColorCounter OR 08 OR 16 OR 32].blue := 21+(ColorCounter * 6);
End;
{ Make Colors Where The Grey Square Overlaps The Bobs }
For ColorCounter := 128 to 255 do
Begin
Pal[ColorCounter].Red := (Pal[ColorCounter-128].Red DIV 4)+14;
Pal[ColorCounter].Green := (Pal[ColorCounter-128].Green DIV 4)+14;
Pal[ColorCounter].Blue := (Pal[ColorCounter-128].Blue DIV 4)+14;
End;
End;
{-[ Draw Grey Square In Background Buffer ]-----------------------------}
Procedure BuildBackground;
Var Y, X : Integer;
Begin
FillChar (BackGround^, SizeOf(BackGround^), 0);
For Y := 50 to 150 do
For X := 100 to 220 do
BackGround^[Y, X] := 128;
End;
{=[ Main Program ]======================================================}
Begin
VGA := Ptr ($A000,$0000);
New (WorkPage);
New (BackGround);
InitializeVariables;
BuildPalette;
BuildBackground;
SetMode13h;
SetPalette (Pal);
Repeat
UpdateBobs; { Update Bob Positions }
WorkPage^ := BackGround^; { Clear WorkPage With Static Image }
DrawBobs; { Draw Bobs }
{ Wait For Retrace }
Repeat Until ((Port[$3DA] AND 8) <> 0);
VGA^ := WorkPage^; { Display Page }
Until KeyPressed;
TextMode (C80);
Dispose (BackGround);
Dispose (WorkPage);
End.
{ PALETTE CODE FOLLOWS }
{
TD> I've seen it done in many places, but I haven't seen any info on
TD> how it's done: What is the basic algorithm for fading from one
TD> palette to another.
Many people do palette fading incorrectly. The correct
way to do it would be to set up a relation such as:
Palette_Element Calculated_Element
--------------- = ------------------
Max_Intensity Current_Intensity
Where Palette_Element is a single element in our master DAC
table, Max_Intensity is the maximum allowable intensity level for
our scale, Current_Intensity is a number between 0 and
Max_Intensity which represents the level we want, and
Calculated_Element is the new value for the element of our DAC
table. But since we want the Calculated_Element, we re-write it
as this equation:
Calculated_Element = Palette_Element * Current_Intensity
-----------------------------------
Max_Intensity
The above equation will allow us to fade a given palette set to
black or from black to a given palette set. To fade out an entire
palette set, you would need to calculate the above for the red,
green, and blue components of each color in the 256 element DAC
table.
Fading from one palette set to another palette set is
very similar. What you must do is fade one palette set to black
while simultaneously fade from black to another palette set and
add the two values. The equation for this is:
CE = ((PE1 * (MI - CI)) + (PE2 * CI)) / MI
Where CE is the calculated element, PE1 and PE2 are corresponding
palette elements from palette 1 and 2, MI is the maximum
intensity in our scale, and CI is the current intensity we want
(num between 0 and MI). }
Unit Palette;
{ Programmed By David Dahl @ FidoNet 1:272/38 }
(* PUBLIC DOMAIN *)
Interface
Type PaletteRec = Record
Red : Byte;
Green : Byte;
Blue : Byte;
End;
PaletteArray = Array [0..255] of PaletteRec;
Procedure SetPalette (Var PaletteIn : PaletteArray);
Procedure FadeFromPaletteToBlack (Var PaletteIn : PaletteArray);
Procedure FadeFromBlackToPalette (Var PaletteIn : PaletteArray);
Procedure FadeFromPalette1ToPalette2 (Var Palette1 : PaletteArray;
Var Palette2 : PaletteArray);
Implementation
Procedure SetPalette (Var PaletteIn : PaletteArray); Assembler;
Asm
{ Get Address of PaletteIn }
LDS SI, PaletteIn
CLD
{ Tell VGA To Start With First Palette Element }
XOR AX, AX
MOV DX, $3C8
OUT DX, AL
{ Wait For Retrace }
MOV DX, $3DA
@VRWait1:
IN AL, DX
AND AL, 8
JZ @VRWait1
{ Set First Half Of Palette }
MOV DX, $3C9
MOV CX, 128 * 3
@PALLOOP1:
LODSB { DON'T use "REP OUTSB" since some VGA cards can't handle it }
OUT DX, AL
LOOP @PALLOOP1
{ Wait For Retrace }
PUSH DX
MOV DX, $3DA
@VRWait2:
IN AL, DX
AND AL, 8
JZ @VRWait2
POP DX
{ Set Last Half Of Palette }
MOV CX, 128 * 3
@PALLOOP2:
LODSB
OUT DX, AL
LOOP @PALLOOP2
End;
Procedure FadeFromPaletteToBlack (Var PaletteIn : PaletteArray);
Var WorkPalette : PaletteArray;
Counter : Integer;
Intensity : Integer;
Begin
For Intensity := 31 downto 0 do
Begin
For Counter := 0 to 255 do
Begin
WorkPalette[Counter].Red :=
(PaletteIn[Counter].Red * Intensity) DIV 32;
WorkPalette[Counter].Green :=
(PaletteIn[Counter].Green * Intensity) DIV 32;
WorkPalette[Counter].Blue :=
(PaletteIn[Counter].Blue * Intensity) DIV 32;
End;
SetPalette (WorkPalette);
End;
End;
Procedure FadeFromBlackToPalette (Var PaletteIn : PaletteArray);
Var WorkPalette : PaletteArray;
Counter : Integer;
Intensity : Integer;
Begin
For Intensity := 1 to 32 do
Begin
For Counter := 0 to 255 do
Begin
WorkPalette[Counter].Red :=
(PaletteIn[Counter].Red * Intensity) DIV 32;
WorkPalette[Counter].Green :=
(PaletteIn[Counter].Green * Intensity) DIV 32;
WorkPalette[Counter].Blue :=
(PaletteIn[Counter].Blue * Intensity) DIV 32;
End;
SetPalette (WorkPalette);
End;
End;
Procedure FadeFromPalette1ToPalette2 (Var Palette1 : PaletteArray;
Var Palette2 : PaletteArray);
Var WorkPalette : PaletteArray;
Counter : Integer;
CrossFade : Integer;
Begin
For CrossFade := 0 to 32 do
Begin
For Counter := 0 to 255 do
Begin
WorkPalette[Counter].Red :=
((Palette1[Counter].Red * (32 - CrossFade)) +
(Palette2[Counter].Red * CrossFade)) DIV 32;
WorkPalette[Counter].Green :=
((Palette1[Counter].Green * (32 - CrossFade)) +
(Palette2[Counter].Green * CrossFade)) DIV 32;
WorkPalette[Counter].Blue :=
((Palette1[Counter].Blue * (32 - CrossFade)) +
(Palette2[Counter].Blue * CrossFade)) DIV 32;
End;
SetPalette (WorkPalette);
End;
End;
End.
TUTORIAL !!
Transparent objects are rather simple. What you do is
set up your palette so pure colors are represented by powers of
two. This way you can "mix" your colors by ORing the values
together. For simplicity's sake, this example will use 3 colors:
Bit 7 6 5 4 3 2 1 0
| | |
| | +----> Red
| +------> Green
+--------> Blue
So now you would set your palette up as follows:
All single colors:
2^0 = 1 -- Red
2^1 = 2 -- Green
2^2 = 4 -- Blue
All possible 2 color mixes:
2^0 OR 2^1 = 1 OR 2 = 3 -- Red + Green = Yellow
2^0 OR 2^2 = 1 OR 4 = 5 -- Red + Blue = Magenta
2^1 OR 2^2 = 2 OR 4 = 6 -- Green + Blue = Cyan
All possible 3 color mixes:
2^0 OR 2^1 OR 2^2 = 1 OR 2 OR 4 = 7 -- R + G + B = White
So our palette is set up as:
0 - Black
1 - Red
2 - Green
3 - Yellow
4 - Blue
5 - Magenta
6 - Cyan
7 - White
Now let's say we have a Red, Green, and a Blue square. The
bitmap of the red square will be made up of bytes of the value 1,
the green square will be made up of the value 2, and the blue
square will be made up of the value 4 as so:
Red Green Blue
11111111 22222222 44444444
11111111 22222222 44444444
11111111 22222222 44444444
11111111 22222222 44444444
To put the squares, you just have to OR put them to your frame
buffer. If they overlap, they will automatically mix as so:
The 3 overlaping bitmaps The 3 overlaping bitmaps
in frame buffer using an in frame buffer showing
OR'd image put: what colors are where:
11111111 RRRRRRRR
11111111 RRRRRRRR
111133332222 RRRRYYYYGGGG
155577776222 RMMMWWWWCGGG
44466666222 BBBCCCCCGGG
44466666222 BBBCCCCCGGG
44444444 BBBBBBBB
The following example program uses this bit scheme:
Bit 7 6 5 4 3 2 1 0
| | | | +-+-+---> Color Intensity (0:Least - 7:Full)
| | | +---------> Red
| | +-----------> Green
| +-------------> Blue
+-----------------> Grey
David Dahl